import datetime
import uuid
import pymysql
import redis
from globals.globals import *
from models import models
from constant.constant import *


accident_SQL = 'SELECT * FROM equipmentalarmtag;'

with my_session() as session:
    accidents = session.execute(accident_SQL).fetchall()

pool = redis.ConnectionPool(host=constant.REDIS_HOST, port=constant.REDIS_PORT, password=constant.REDIS_PASSWORD,
                                 decode_responses=True)


class AccidentModel():

    equip = None

    def __init__(self,accident):
        # 构造模型
        self.ID = accident.ID
        self.alarm_name = accident.alarm_name
        self.alarm_grade_code = accident.alarm_grade_code
        self.alarm_group_code = accident.alarm_group_code
        self.alarm_class_code = accident.alarm_class_code
        self.alarm_position =   accident.alarm_position
        self.alarmmodeID =      accident.alarmmodeID
        self.taos_equipment_code = accident.taos_equipment_code
        self.equipmentcode = accident.equipmentcode
        self.sub_equipment = accident.sub_equipment
        self.calc_class = accident.calc_class
        self.taos_field_name = accident.taos_field_name
        self.ifconditions = accident.ifconditions.split(';')
        self.symbol = accident.symbol.split(';')
        self.standvalue = accident.standvalue.split(';')
        self.condition_relation = accident.condition_relation
        self.alarm_deadzone = accident.alarm_deadzone
        self.alarm_duration = accident.alarm_duration
        self.redistag = accident.redistag
        self.is_stop = accident.is_stop
        self.description = accident.description
        self.is_writeredis = accident.is_writeredis
        self.readredistable = accident.readredistable
        self.writeredistable = accident.writeredistable
        self.equipmentID = accident.equipmentID

        # 连接对象
        self.r = redis.Redis(connection_pool=pool)

        # 辅助参数
        self.accident = {'uuid' : '', 'start_time' : None}

    # 生成报警信息
    def alarm_create(self,uuid,mode,start_time):
        with my_session() as session:
            session.add(models.Alarmeventdetail(
            UUID=uuid,
            equipmentID=self.equipmentID,
            equipmentcode=self.equipmentcode,
            alarm_name=self.alarm_name,
            alarm_starttime= str(start_time),
            alarm_endtime= '',
            alarm_duration_time= '',
            description= mode,
            alarm_class_code=self.alarm_class_code,
            alarm_grade_code=self.alarm_grade_code,
            alarm_group_code=self.alarm_group_code,
            alarm_year =  start_time.strftime('%Y'),
            alarm_month = start_time.strftime('%Y-%m'),
            alarm_day =   start_time.strftime('%Y-%m-%d'),
            alarm_hour =  start_time.strftime('%Y-%m-%d %H'),
            alarm_minute =start_time.strftime('%Y-%m-%d %H:%M'),
            alarm_second =start_time.strftime('%Y-%m-%d %H:%M:%S'),
            alarm_status = UNHANDLE
        ))


    # 更新报警信息
    def alarm_update(self,uuid,start_time):
        time_end = datetime.datetime.now()
        alarm_endtime = str(time_end)
        alarm_duration_time = str(int(time_end.timestamp() - start_time.timestamp()))
        SQL = 'update alarmeventdetail set alarm_endtime = "{alarm_endtime}", alarm_duration_time = "{alarm_duration_time}" ' \
              'where UUID = "{uuid}"'.format(alarm_endtime=alarm_endtime, alarm_duration_time=alarm_duration_time, uuid=uuid)
        with my_session() as session:
            session.execute(SQL)
        self.accident['uuid'] = ''


    # 故障判断
    def accident_judge(self):
        expression = list(zip(self.ifconditions, self.symbol, self.standvalue))
        result_count = 0
        for exp in expression:
            ifcon = self.r.hget(self.readredistable, exp[0])
            standvalue = exp[2]
            result = operators[exp[1]](ifcon, standvalue) if ifcon else None
            result_count += 1 if result else 0
        if len(expression) == result_count:
            if not self.accident['uuid']:
                self.accident['uuid'] = str(uuid.uuid4())
                self.accident['start_time'] = datetime.datetime.now()
                self.alarm_create(self.accident['uuid'], EQUIP_ACCI, self.accident['start_time'])
                self.r.hset(EQUIP_TABLE, str(self.equipmentID) + '_accident', 1)
                if self.sub_equipment:
                    self.r.hset(EQUIP_TABLE, str(self.equipmentID) + '_' + str(self.sub_equipment) + '_accident',1)
            self.accident_time_update()
        else:
            if self.accident['uuid']:
                self.alarm_update(self.accident['uuid'], EQUIP_ACCI, self.accident['start_time'])
                self.r.hset(EQUIP_TABLE, str(self.equipmentID) + '_accident', 0)
                if self.sub_equipment:
                    self.r.hset(EQUIP_TABLE, str(self.equipmentID) + '_' + str(self.sub_equipment) + '_accident' ,0)


    # 设备故障时间更新
    def accident_time_update(self):
        # 当前设备故障已记录
        if self.equipmentID == AccidentModel.equip:
            return
        # 设备初始化
        elif not AccidentModel.equip:
            AccidentModel.equip = self.equipmentID
            # 当前设备故障时间++
            accittime = self.r.hget(EQUIP_TABLE, self.equipmentID + '_accitime') if self.r.hget(EQUIP_TABLE,
                                                                                                     self.equipmentID + '_accitime') else 0
            accittime_new = round((eval(accittime) * 3600 + ACCI_LOOP_TIME) / 3600, 1)
            if accittime != accittime_new:
                self.r.hset(EQUIP_TABLE, self.equipmentID + '_accitime', accittime_new)
                self.r.hset(EQUIP_TABLE, self.equipmentID + '_accitime_writetime', datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
            return
        # 设备故障处理
        elif self.equipmentID == AccidentModel.equip:
            # 当前设备故障时间++
            accittime = self.r.hget(EQUIP_TABLE, self.equipmentID + '_accitime') if self.r.hget(EQUIP_TABLE, self.equipmentID + '_accitime') else 0
            accittime_new = round((eval(accittime) * 3600 + ACCI_LOOP_TIME) / 3600, 1)
            if accittime != accittime_new:
                self.r.hset(EQUIP_TABLE, self.equipmentID + '_accitime', accittime_new)
                self.r.hset(EQUIP_TABLE, self.equipmentID + '_accitime_writetime', datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
            return
        # 设备切换
        elif AccidentModel.equip is not None and self.equipmentID != AccidentModel.equip:
            AccidentModel.equip = self.equipmentID
            # 当前设备故障时间++
            accittime = self.r.hget(EQUIP_TABLE, self.equipmentID + '_accitime') if self.r.hget(
                EQUIP_TABLE, self.equipmentID + '_accitime') else 0
            accittime_new = round((eval(accittime) * 3600 + ACCI_LOOP_TIME) / 3600, 1)
            if accittime != accittime_new:
                self.r.hset(EQUIP_TABLE, self.equipmentID + '_accitime', accittime_new)
                self.r.hset(EQUIP_TABLE, self.equipmentID + '_accitime_writetime', datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
            return


accidents_nodels = list()
def get_accident_model():
    '''
    构造报警模型列表
    '''
    for accident in accidents:
        accidents_nodels.append(AccidentModel(accident))

get_accident_model()


def accident_job():
    '''
    各报警模型执行报警方法
    '''
    with server_status():
        for model in accidents_nodels[0:1]:
            model.accident_judge()
